interface IHandleObj {
  handlers: Function[];
  once: boolean;
}

class EventEmiter {
  eventMap: Map<string, IHandleObj>;
  constructor() {
    this.eventMap = new Map();
  }
  /**
   * 添加事件
   */
  on(name: string, handler: Function, once = false) {
    const currEvent = this.eventMap.get(name);
    if (!currEvent) {
      const eventObj: IHandleObj = {
        handlers: [handler],
        once
      };
      this.eventMap.set(name, eventObj);
    }
    else {
      currEvent.handlers.push(handler);
      currEvent.once = once;
    }
  }
  once(name: string, handler: Function) {
    this.on(name, handler, true);
  }
  off(name: string) {
    this.eventMap.has(name) && this.eventMap.delete(name);
  }

  emit(name: string) {
    const currEvent = this.eventMap.get(name);
    if (currEvent) {
      currEvent.handlers.forEach(item => item());

      if (currEvent?.once) {
        this.off(name);
      }
    }
  }
}


const e = new EventEmiter();
e.on('click', () => {
  console.log('click1');
});
e.on('click', () => {
  console.log('click2');
});
e.on('click', () => {
  console.log('click3');
});
e.once('click', () => {
  console.log('once');
});
e.emit('click');
e.emit('click');
